package controllers

import config._
import play.api.libs.json.Json
import play.api.mvc.{AbstractController, ControllerComponents}
import utils.ReadExcel

import javax.inject.Inject
import scala.concurrent.ExecutionContext
import scala.math.log10

class MetaController @Inject()(cc: ControllerComponents)
                              (implicit exec: ExecutionContext) extends AbstractController(cc) with MyRow with MyAwait with MyString with MyFile {


  def mdSdPage = Action { implicit request =>
    Ok(views.html.meta.mdSdPage())
  }

  def riNiAlkPage = Action { implicit request =>
    Ok(views.html.meta.riNiAlkPage())
  }

  def metaPage = Action{implicit request=>
    Ok(views.html.meta.metaPage())
  }

  def getMdSdData = Action { implicit request =>
    val lines = s"${Global.path}/config/meta.txt".readLines.map(_.split("\t"))
    val table = lines.map(x => x.zipWithIndex.map { y => y._2.toString -> y._1 }.toMap)


    val heatmap = {
      val data = "GeneID,mRNA,EXP\n" + lines.zipWithIndex.flatMap { x =>
        x._1.slice(2, 20).zipWithIndex.map { y =>
          x._2 + "," + y._2 + "," + log2(y._1.toDouble)
        }
      }.mkString("\n")
      val xAxis = lines.map(_.head)

      Json.obj("xAxis" -> xAxis, "csv" -> data)
    }

    Ok(Json.obj("table" -> table, "heatmap" -> heatmap))
  }

  def log2(x: Double): Double = log10(x + 1) / log10(2.0)

  def getMetaName = Action { implicit request =>
    val name = s"${Global.path}/meta".listFile.map(_.getName.split('.').init.mkString("."))
    Ok(Json.toJson(name))
  }

  def getByName(name: String) = Action { implicit request =>

    println(name)
    val n = if (name == "WW(80)_WD(25)_WL353LH_cold") {
      "WW(80%)_WD(25%)_WL353LH_cold"
    } else if (name == "Medicago sativa L. cv. Ladak ,）和根瘤菌（根瘤菌Dormal 菌株") {
      "Medicago sativa L. cv. Ladak+,）和根瘤菌（根瘤菌Dormal 菌株"
    } else {
      name
    }

    val lines = ReadExcel.xlsx2Lines(s"${Global.path}/meta/$n.xlsx".toFile).map(_.split("\t"))
    val header = lines.head.map(x => if (x == "NA") "" else x)
    val table = lines.tail.zipWithIndex.map { case (x, i) => x.zipWithIndex.map { y => y._2.toString -> y._1 }.toMap ++ Map("linesNum" -> i.toString) }

    Ok(Json.obj("table" -> table, "header" -> header))


  }


  def getHeatmapPlotData(name: String, selected: String) = Action { implicit request =>
    val n = if (name == "WW(80)_WD(25)_WL353LH_cold") {
      "WW(80%)_WD(25%)_WL353LH_cold"
    } else if (name == "Medicago sativa L. cv. Ladak ,）和根瘤菌（根瘤菌Dormal 菌株") {
      "Medicago sativa L. cv. Ladak+,）和根瘤菌（根瘤菌Dormal 菌株"
    } else {
      name
    }


    val lines = ReadExcel.xlsx2Lines(s"${Global.path}/meta/$n.xlsx".toFile).map(_.split("\t"))
    val header = lines.head.map(x => if (x == "NA") "" else x)

    val (min, max, proId) = name match {

      case "Alfalfa (Caoyuan No.2), treatment of infection thrips" => (8, 13, 0)
      case "Alfalfa (dsao1-t), biological fertilizer treatment" => (2, 11, 1)
      case "Alfalfa (M. sativa cv. Wudi), KH2PO4 and Non-KH2PO4 treatment" => (7, 19, 0)
      case "Alfalfa Zhongmu No.1, Light and Non-light Treatment, Bud stage" => (4, 6, 0)
      case "Alfalfa [Gold Empress (Gold) and Bara 310 SC (Bara)], Graphene treatment" => (2, 17, 1)
      case "Alfalfa(M. sativa cv. Wudi), Pi- deficient treatment" => (10, 22, 0)
      case "Alfalfa(WL525), NaCl treatment, root" => (1, 41, 0)
      case "Alfalfa, TNT treatment" => (16, 26, 4)
      case "NI-Alkali vs NI-Control" => (2, 4, 0)
      case "RI-Alkali vs NI-Alkali" => (2, 4, 0)
      case "RI-Alkali vs RI-Control" => (2, 4, 0)
      case "RI-Control vs NI-Control" => (2, 4, 0)
      case "WW(80)_WD(25)_WL353LH_cold" => (12, 18, 1)
      case "ZM_Salt_(200 mM NaCl）" => (6, 12, 3)


    }
    val yAxis = header.slice(min, max)

    val selectArray = selected.split(",").map(_.toInt)
    val selectLines = selectArray.map { x =>
      lines.tail(x)
    }

    val heatmap = {
      val data = "GeneID,mRNA,EXP\n" + selectLines.zipWithIndex.flatMap { x =>
        x._1.slice(min, max).zipWithIndex.map { y =>
          if (y._1 == "NA" || y._1.trim == "" || y._1.trim == "-") {
            x._2 + "," + y._2 + ",0"
          } else {
            x._2 + "," + y._2 + "," + log2(y._1.toDouble)
          }
        }
      }.mkString("\n")
      val xAxis = lines.tail.map(_(proId))

      Json.obj("xAxis" -> xAxis, "csv" -> data, "yAxis" -> yAxis, "title" -> name)
    }

    val line = {
      val data = selectLines.map { x =>
        Json.obj("name" -> x(proId), "data" -> x.slice(min, max).map { y =>
          if (y == "NA" || y.trim == "" || y.trim == "-") {
            0
          } else {
            y.toDouble
          }

        })
      }
      val xAxis = header.slice(min, max)

      Json.obj("xAxis" -> xAxis, "series" -> data, "title" -> name)

    }

    Ok(Json.obj("heatmap" -> heatmap, "line" -> line))

  }


  def getRiNiAlkData = Action { implicit request =>
    val path = s"${Global.path}/config"
    val json = (1 to 4).map { i =>
      val lines = s"$path/riNiAlk${i}.txt".readLines.map(_.split("\t"))
      val header = lines.head
      val data = lines.tail.map { x => x.zipWithIndex.map(y => y._2.toString -> y._1).toMap }
      s"$i" -> Json.obj("header" -> header, "data" -> data)
    }.toMap
    Ok(Json.toJson(json))
  }



}
